package cn.iocoder.yudao.module.trade.cart.service;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.api.product.sku.ProductSkuApi;
import cn.iocoder.yudao.module.api.product.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.api.shop.category.eums.ShopCategoryCodeEnum;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.trade.cart.dal.dataobject.CartDO;
import cn.iocoder.yudao.module.trade.cart.dal.mysql.CartMapper;
import cn.iocoder.yudao.module.trade.cart.vo.AppCartAddReqVO;
import cn.iocoder.yudao.module.trade.cart.vo.AppCartResetReqVO;
import cn.iocoder.yudao.module.trade.cart.vo.AppCartUpdateCountReqVO;
import cn.iocoder.yudao.module.trade.cart.vo.AppCartUpdateSelectedReqVO;
import jakarta.annotation.Nullable;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.api.trade.ErrorCodeConstants.CARD_ITEM_NOT_FOUND;

/**
 * 购物车 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class CartServiceImpl implements CartService {

    @Resource
    private CartMapper cartMapper;

    @Resource
    private ProductSkuApi productSkuApi;
    @Resource
    private ShopInfoApi shopInfoApi;

    @Override
    public Long addCart(Long userId, AppCartAddReqVO addReqVO) {
        // 查询 TradeCartDO
        CartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId());
        // 校验 SKU
        Integer count = addReqVO.getCount();
        ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count);

        // 情况一：存在，则进行数量更新
        if (cart != null) {
            CartDO updateObj = new CartDO();
            updateObj.setId(cart.getId());
            updateObj.setSelected(false);
            updateObj.setCount(cart.getCount() + count);
            cartMapper.updateById(updateObj);
            return cart.getId();
            // 情况二：不存在，则进行插入
        } else {
            cart = new CartDO();
            cart.setShopId(sku.getShopId());
            cart.setUserId(userId);
            cart.setSelected(false);
            cart.setSpuId(sku.getSpuId());
            cart.setSkuId(sku.getId());
            cart.setCount(count);
            cartMapper.insert(cart);
        }
        return cart.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCartCount(Long userId, AppCartUpdateCountReqVO updateReqVO) {
        // 校验 TradeCartDO 存在
        CartDO cart = cartMapper.selectById(updateReqVO.getId(), userId);
        if (cart == null) {
            throw exception(CARD_ITEM_NOT_FOUND);
        }
        if (updateReqVO.getCount() <= 0) {
            cartMapper.deleteById(cart.getId());
        }
        // 校验产品 SKU
        checkProductSku(cart.getSkuId(), updateReqVO.getCount());

        // 更新数量
        CartDO updateObj = new CartDO();
        updateObj.setId(cart.getId());
        updateObj.setCount(updateReqVO.getCount());
        cartMapper.updateById(updateObj);
    }

    @Override
    public void updateCartSelected(Long userId, AppCartUpdateSelectedReqVO updateSelectedReqVO) {
        cartMapper.updateByIds(updateSelectedReqVO.getIds(), userId,
                new CartDO().setSelected(updateSelectedReqVO.getSelected()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetCart(Long userId, AppCartResetReqVO resetReqVO) {
        // 第一步：删除原本的购物项
        CartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId);
        if (oldCart == null) {
            throw exception(CARD_ITEM_NOT_FOUND);
        }
        cartMapper.deleteById(oldCart.getId());

        // 第二步：添加新的购物项
        CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId());
        if (newCart != null) {
            AppCartUpdateCountReqVO reqVO = new AppCartUpdateCountReqVO();
            reqVO.setId(newCart.getId());
            reqVO.setCount(resetReqVO.getCount());
            updateCartCount(userId, reqVO);
        } else {
            AppCartAddReqVO reqVO = new AppCartAddReqVO();
            reqVO.setSkuId(resetReqVO.getSkuId());
            reqVO.setCount(resetReqVO.getCount());
            addCart(userId, reqVO);
        }
    }

    /**
     * 购物车删除产品
     *
     * @param userId 用户编号
     * @param ids    产品 SKU 编号的数组
     */
    @Override
    public void deleteCart(Long userId, Collection<Long> ids) {
        // 查询 TradeCartDO 列表
        List<CartDO> carts = cartMapper.selectListByIds(ids, userId);
        if (CollUtil.isEmpty(carts)) {
            return;
        }
        // 批量标记删除
        cartMapper.deleteByIds(convertSet(carts, CartDO::getId));
    }

    @Override
    public void deleteCart(Long userId, @Nullable Long shopId) {
        // 查询 TradeCartDO 列表
        List<CartDO> carts = getCartList(userId, shopId);
        if (CollUtil.isEmpty(carts)) {
            return;
        }
        // 批量标记删除
        cartMapper.deleteByIds(carts.stream().map(CartDO::getId).toList());
    }

    @Override
    public Integer getCartCount(Long userId, @Nullable Long shopId) {
        if (shopId == null || shopId <= 0) {
            // 若不传店铺编号，则只获取商城产品类的，排除美食、家政类的
            Set<Long> shopIds = shopInfoApi.getShopIdsByCategoryCode(ShopCategoryCodeEnum.MALL.getCode());
            return cartMapper.selectSumByUserIdAndShopIds(userId, shopIds);
        }
        return cartMapper.selectSumByUserIdAndShopId(userId, shopId);
    }

    @Override
    public List<CartDO> getCartList(Long userId, @Nullable Long shopId) {
        List<CartDO> carts;
        if (shopId == null || shopId <= 0) {
            // 若不传店铺编号，则只获取商城产品类的，排除美食、家政类的
            Set<Long> shopIds = shopInfoApi.getShopIdsByCategoryCode(ShopCategoryCodeEnum.MALL.getCode());
            carts = cartMapper.selectListByUserIdAndShopIds(userId, shopIds);
        } else {
            carts = cartMapper.selectListByUserIdAndShopId(userId, shopId);
        }
        return carts;
    }

    @Override
    public List<CartDO> getCartList(Long userId, Set<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return cartMapper.selectListByUserIdAndIds(userId, ids);
    }

    @Override
    public void deleteCartIfSpuDeleted(List<CartDO> carts, List<ProductSpuRespDTO> spus) {
        // 如果 SPU 被删除，则删除购物车对应的产品。延迟删除
        carts.removeIf(cart -> {
            if (spus.stream().noneMatch(spu -> spu.getId().equals(cart.getSpuId()))) {
                cartMapper.deleteById(cart.getId());
                return true;
            }
            return false;
        });
    }

    /**
     * 校验产品 SKU 是否合法
     * 1. 是否存在
     * 2. 是否下架
     * 3. 库存不足
     *
     * @param skuId 产品 SKU 编号
     * @param count 产品数量
     * @return 产品 SKU
     */
    private ProductSkuRespDTO checkProductSku(Long skuId, Integer count) {
        return productSkuApi.validateSku(skuId, count);
    }

}
